home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
MCASM.RAR
/
MC_ASM.EXE
/
WROX_ASM
/
CH3
/
PIANO9.ASM
next >
Wrap
Assembly Source File
|
1994-11-14
|
8KB
|
257 lines
;////////////////////////////////////////////////////////////
;Program 3.2. Resident Beeper.
;////////////////////////////////////////////////////////////
; PIANO9.
; This TSR program is activated by pressing
; <Ctrl> + <Right Shift>. It is protected from
; reloading twice and uninstall itself. To uninstall the
; PIANO9 from memory you should run it with the switch
; /r or /R in the command line.
; Having been activated PIANO9 produces short sounds
; of different tones for any key pressed. You can stop
; by pressing <Esc>.
; Demo program for ExpAsm Chapter3 "Fundamental System
; Programming Techniques".
;
CODE GROUP care9,init9
; RESIDENT PART:
care9 SEGMENT para
ASSUME cs:code,ds:code,es:code
Flag DB 0
OldInt9 DW 2 dup(?)
OldInt2F DW 2 dup(?)
TSR_PSP_Addr DW ?
our_TSR_Segm DW ?
our_TSR_Offs DW ?
;NEW ISR FOR INTERRUPT 09h:
NewInt9 PROC far
push ax
push es
xor ax,ax
mov es,ax
test BYTE ptr es:[417h],1; Check Status
; Byte for <Right
; Shift> pressed.
jz No_Keys
test BYTE ptr es:[417h],4; Check Status
; Byte for <Ctrl>
; pressed.
jz No_Keys
mov cs:Flag,1 ; Set Flag (<Ctrl-RShift>
; has been pressed).
Ex_Int9:
pop es ; Return to the standard
pop ax ; ISR
jmp dword ptr cs:OldInt9
No_Keys:
cmp cs:Flag,1 ; If Flag<>1, then return
jne Ex_Int9 ; from the procedure.
in al,60h ; Load the SCAN code of
; pressed key into AL.
cmp al,1
jne Beep
mov cs:Flag,0 ; If ESC, then return from
jmp Ex_Int9 ; the procedure and clear
; Flag.
Beep:
push cx
xor ah,ah ; AL contains the SCAN code of
; the key pressed.
mov cl,150 ; Multiplier for SCAN code
; of every key.
mul cl
mov cx,ax ; CX contains the frequency now
mov al,0B6h ; Set channel 2 of I8253
out 43h,al
mov ax,cx
out 42h,al ; Send lower byte of
; frequency.
mov al,ah ; Send higher byte of
out 42h,al ; frequency.
in al,61h
mov ah,al
or al,3
out 61h,al
xor cx,cx
Wait_a_little: ; Sound generation delay.
loop Wait_a_Little
pop cx
mov al,ah
out 61h,al
and BYTE ptr es:[417h],11111010b
in al,61h ; Process pressed
mov ah,al ; keys in proper way
or al,01000000b; (instead of standard
out 61h,al ; ISR for INT 09h)
mov al,ah
out 61h,al
mov al,20h ; Make the PIC to finish
out 20h,al ; interrupt processing by
; sending EOI command.
pop es
pop ax
iret
NewInt9 ENDP
;NEW ISR FOR INTERRUPT 2Fh:
NewInt2F PROC far
cmp ah,0E0h ; Is Number correct?
je Our_proc
jmp DWORD ptr cs:OldInt2f
Our_proc: cmp al,0 ; If install check command
jne Ex_int2f ; then
mov al,0FFh ; set installation flag.
Ex_int2f: iret
NewInt2F ENDP
care9 ENDS
;INITIALIZATION PART:
init9 SEGMENT
start:
jmp Go_on ; Skip local data area.
Mess1 DB 'I really do not want to be loaded for the'
DB ' second time! <PIANO9>',10,13,'$'
Mess2 DB 'PIANO9 has been successfully removed'
DB 10,13,'$'
Mess3 DB 'Sorry, PIANO9 can not be removed.',10,13,'$'
Mess4 DB 'Unknown switcher.',10,13,'$'
Go_on:
mov di,81h ;Search for a slash
mov cl,es:[di-1]
mov al,'/'
repne scasb
jne Install ;If no switch in the command
;line then install ISRs.
cmp byte ptr es:[di],'R';Look for 'R'or'r'
je Remove_it
cmp byte ptr es:[di],'r'
je Remove_it ; Switch is OK.
; Remove the resident
push cs
pop ds
mov dx,cs:OFFSET Mess4 ; Warn the user about
mov ah,9 ; a wrong switch.
int 21h
jmp Exit
Remove_it:
call Remove
Exit: mov ax,4C00h; Exit the program.
int 21h
Install:
push ds
push cs
pop ds
mov ah,0E0h ;Number=0E0h
mov al,0 ;Installation Check command.
int 2Fh
cmp al,0 ;If AL<>0, then program
;has already installed.
jz Cont
mov dx,cs:OFFSET Mess1 ; Tell the user that
mov ah,09h ; resident is already
int 21h ; installed.
jmp Exit
Cont: mov ah,62h ; Get PSP segment
int 21h ; address.
mov si,es
mov es,es:[2ch]
mov ah,49h ; Free DOS
int 21h ; environment
mov cs:TSR_PSP_Addr,si ; Save PSP of the
; TSR part.
mov ax,352Fh
int 21h ; Get vector 2Fh.
mov OldInt2F,bx ; Save vector 2Fh.
mov OldInt2F+2,es
mov dx,OFFSET NewInt2F; Set new vector 2Fh
mov ax,252Fh
int 21h
mov ax,3509h
int 21h ; Get vector 09h.
mov cs:OldInt9,bx ; Save vector 09h.
mov cs:OldInt9+2,es
mov dx,OFFSET NewInt9
mov cs:our_TSR_Segm,ds ; Save Segment of our ISR.
mov cs:our_TSR_Offs,dx ; Save Offset of our ISR.
; Set new vector
mov ax,2509h ; for interrupt
int 21h ; 09h.
pop dx ; Calculate the
sub dx,init9 ; size of the
neg dx ; resident part.
mov ax,3100h ; Terminate and
int 21h ; Stay Resident.
Remove PROC near
push ds
push cs
pop ds
mov ax,3509h ; Get Segment and Offset
int 21h ; of the last ISR on vector 09h.
mov cx,es:[our_TSR_Segm];Get Segment and
mov si,es:[our_TSR_Offs];Offset of our ISR
mov ax,es
cmp cx,ax ; Compare Segment Addresses.
jnz Do_not_remove
cmp bx,si ; Compare Offsets.
jz Free_mem
Do_not_remove:
mov dx,cs:OFFSET Mess3 ; Tell the user that
mov ah,09h ; the resident can't be
int 21h ; removed.
pop ds
ret ; Don't remove the
; resident.
Free_mem:
push ds
mov dx,es:[OldInt9] ; Copy the
mov ds,es:[OldInt9+2]; old vector to DS:DX.
mov ax,2509h ; Restore vector 09h
int 21h ; using DOS service.
mov dx,es:[OldInt2F] ; Copy the
mov ds,es:[OldInt2F+2]; old vector to DS:DX
mov ax,252Fh ; Restore vector 2Fh
int 21h ; using DOS service.
pop ds
mov es,es:[TSR_PSP_Addr]; Load ES with
; Segment Address of
; the resident part.
mov ah,49h ; Free MCB allocated for
int 21h ; resident part.
mov dx,cs:OFFSET Mess2 ; Tell the user that
mov ah,09h ; resident has been
int 21h ; removed.
pop ds
ret
Remove ENDP
init9 ENDS
END start